package com.xsf.jieyou.provider.service;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.nacos.client.utils.StringUtils;
import com.xsf.jieyou.provider.api.ProviderTbUserService;
import com.xsf.jieyou.provider.domain.TbUser;
import com.xsf.jieyou.provider.fallback.TbUserServiceFallback;
import com.xsf.jieyou.provider.mapper.TbUserMapper;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.Date;

/**
 * 用户，Dubbo服务实现类。
 * <p>
 * Description:Dubbo 服务实现类，
 * 需要注意的是，需要在启动类加载 DubboSentinelConfiguration 配置，不然 熔断降级 将无法返回托底数据
 * </p>
 *
 * @author xsf
 * @version v1.0.0
 * @date 2019/11/15 0015
 **/
@Service(version = "1.0.0")
public class ProviderTbUserServiceImpl implements ProviderTbUserService {

    @Resource
    private TbUserMapper tbUserMapper;
    @Resource
    private BCryptPasswordEncoder passwordEncoder;

    /**
     * 新增 用户。
     * //@SentinelResource : Dubbo熔断器
     *
     * @param tbUser 用户对象
     * @return 如果返回值大于 0，则表示新增用户成功
     */
    @Override
    @SentinelResource(value = "insertTbUser", fallbackClass = TbUserServiceFallback.class, fallback =
            "insertTbUserFallback")
    public int insert(TbUser tbUser) {
        // ############   测试熔断（success）   #################################
        /*if (1 + 1 == 2) {
            throw new RuntimeException();
        }*/
        // ############   测试熔断   #################################

        //初始化系统用户
        this.initUmsAdmin(tbUser);
        return this.tbUserMapper.insertSelective(tbUser);
    }

    /**
     * 通过用户名获取用户对象
     *
     * @param username 用户名
     * @return 用户对象 {@link TbUser}
     */
    @Override
    @SentinelResource(value = "getByUsername", fallbackClass = TbUserServiceFallback.class, fallback =
            "getTbUserFallback")
    public TbUser get(String username) {
        return this.getTbUserByUsername(username);
    }

    /**
     * 通过 用户对象(用户名||手机号码) 获取 完整的用户对象
     *
     * @param tbUser {@link TbUser}
     * @return 用户对象 {@link TbUser}
     */
    @Override
    @SentinelResource(value = "getByTbUser", fallbackClass = TbUserServiceFallback.class, fallback =
            "getTbUserFallback")
    public TbUser get(TbUser tbUser) {
        // 手机号
        if (!StringUtils.isEmpty(tbUser.getPhone())) {
            Example example = new Example(TbUser.class);
            example.createCriteria().andEqualTo("phone", tbUser.getPhone());
            return this.tbUserMapper.selectOneByExample(example);
        }
        // 用户名
        return this.getTbUserByUsername(tbUser.getUsername());
    }

    /**
     * 通过 用户ID 获取 用户对象
     *
     * @param userId {@link Long} 用户ID
     * @return 用户对象 {@link TbUser}
     */
    @Override
    @SentinelResource(value = "getByTbUser", fallbackClass = TbUserServiceFallback.class, fallback =
            "getTbUserFallback")
    public TbUser get(Long userId) {
        return this.tbUserMapper.selectByPrimaryKey(userId);
    }

    /**
     * 根据主键 更新用户
     *
     * @param tbUser {@link TbUser}
     * @return 用户对象 {@link TbUser}
     */
    @Override
    @SentinelResource(value = "updateTbUser", fallbackClass = TbUserServiceFallback.class, fallback =
            "updateTbUser")
    public int update(TbUser tbUser) {
        return this.tbUserMapper.updateByPrimaryKeySelective(tbUser);
    }

    /**
     * 校验用户名唯一性
     *
     * @param username 用户名
     * @return 用户对象 {@link TbUser}
     */
    @Override
    @SentinelResource(value = "validateUsername", fallbackClass = TbUserServiceFallback.class, fallback =
            "validateUsername")
    public int validateUsername(String username) {
        Example example = new Example(TbUser.class);
        example.createCriteria().andEqualTo("username", username);
        return this.tbUserMapper.selectCountByExample(example);
    }

    /**
     * 校验手机号唯一性
     *
     * @param phone 手机号
     * @return 用户对象 {@link TbUser}
     */
    @Override
    @SentinelResource(value = "validatePhoneNum", fallbackClass = TbUserServiceFallback.class, fallback =
            "validatePhoneNum")
    public int validatePhoneNum(String phone) {
        Example example = new Example(TbUser.class);
        example.createCriteria().andEqualTo("phone", phone);
        return this.tbUserMapper.selectCountByExample(example);
    }

    /**
     * 通过用户名获取用户对象
     *
     * @param username 用户名
     * @return {@link TbUser}
     */
    private TbUser getTbUserByUsername(String username) {
        Example example = new Example(TbUser.class);
        example.createCriteria().andEqualTo("username", username);
        return this.tbUserMapper.selectOneByExample(example);
    }

    /**
     * 初始化系统用户
     *
     * @param tbUser 系统用户对象{@link TbUser}
     */
    private void initUmsAdmin(TbUser tbUser) {
        Date date = new Date();
        tbUser.setCreateTime(date);
        tbUser.setUpdated(date);
        // 默认昵称
        if (StringUtils.isEmpty(tbUser.getNickName())) {
            tbUser.setNickName("用户" + tbUser.getId());
        }
        // 密码加密处理
        if (StringUtils.isNotEmpty(tbUser.getPassword())) {
            tbUser.setPassword(this.passwordEncoder.encode(tbUser.getPassword()));
        }
    }

}
